#include "sw_i2c_ex.h"

#include <string.h>
#include <stddef.h>

#define DATA_BUF_SIZE 512

uint8_t sw_i2c_ex_read_byte(struct sw_i2c_dev *dev, uint8_t slave_addr, uint8_t reg_addr, uint8_t *data)
{
    uint8_t data_buf[1];
    struct sw_i2c_msg sw_i2c_ex_msgs;

    if(dev == NULL || data == NULL) {
        return 1;
    }

    sw_i2c_ex_msgs.buf = data_buf;
    // write reg_addr
    sw_i2c_ex_msgs.addr = slave_addr;
    sw_i2c_ex_msgs.flags = SW_I2C_FLAG_WR;
    sw_i2c_ex_msgs.buf[0] = reg_addr;
    sw_i2c_ex_msgs.len = 1;
    sw_i2c_transfer(dev, &sw_i2c_ex_msgs, 1);
    // read data
    sw_i2c_ex_msgs.addr = slave_addr;
    sw_i2c_ex_msgs.flags = SW_I2C_FLAG_RD;
    sw_i2c_ex_msgs.len = 1;
    sw_i2c_transfer(dev, &sw_i2c_ex_msgs, 1);
    *data = sw_i2c_ex_msgs.buf[0];
    return 0;
}


uint8_t sw_i2c_ex_write_byte(struct sw_i2c_dev *dev, uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
{
    uint8_t data_buf[1 + 1];
    struct sw_i2c_msg sw_i2c_ex_msgs;

    if(dev == NULL) {
        return 1;
    }
    sw_i2c_ex_msgs.buf = data_buf;
    // write data
    sw_i2c_ex_msgs.addr = slave_addr;
    sw_i2c_ex_msgs.flags = SW_I2C_FLAG_WR;
    sw_i2c_ex_msgs.buf[0] = reg_addr;
    sw_i2c_ex_msgs.buf[1] = data;
    sw_i2c_ex_msgs.len = 2;
    sw_i2c_transfer(dev, &sw_i2c_ex_msgs, 1);
    return 0;
}

uint8_t sw_i2c_ex_read_bytes(struct sw_i2c_dev *dev, uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    uint8_t data_buf[DATA_BUF_SIZE] = {0};
    struct sw_i2c_msg sw_i2c_ex_msgs;
    if(dev == NULL || data == NULL || len > DATA_BUF_SIZE) {
        return 1;
    }

    sw_i2c_ex_msgs.buf = data_buf;
    // write reg_addr
    sw_i2c_ex_msgs.addr = slave_addr;
    sw_i2c_ex_msgs.flags = SW_I2C_FLAG_WR;
    sw_i2c_ex_msgs.buf[0] = reg_addr;
    sw_i2c_ex_msgs.len = 1;
    sw_i2c_transfer(dev, &sw_i2c_ex_msgs, 1);

    // read data
    sw_i2c_ex_msgs.addr = slave_addr;
    sw_i2c_ex_msgs.flags = SW_I2C_FLAG_RD;
    sw_i2c_ex_msgs.len = len;
    sw_i2c_transfer(dev, &sw_i2c_ex_msgs, 1);
    memcpy(data, data_buf, len);

    return 0;
}
uint8_t sw_i2c_ex_write_bytes(struct sw_i2c_dev *dev, uint8_t slave_addr, uint8_t reg_addr, const uint8_t *data, uint16_t len)
{
    uint8_t data_buf[DATA_BUF_SIZE + 1] = {0};
    struct sw_i2c_msg sw_i2c_ex_msgs;

    if(dev == NULL || data == NULL || len > DATA_BUF_SIZE) {
        return 1;
    }

    sw_i2c_ex_msgs.buf = data_buf;
    // write reg_addr
    sw_i2c_ex_msgs.addr = slave_addr;
    sw_i2c_ex_msgs.flags = SW_I2C_FLAG_WR;
    sw_i2c_ex_msgs.buf[0] = reg_addr;
    memcpy(&sw_i2c_ex_msgs.buf[1], data, len);
    sw_i2c_ex_msgs.len = len + 1;
    sw_i2c_transfer(dev, &sw_i2c_ex_msgs, 1);

    return 0;  
}
